/*
 * This file is part of SSHTTPD.
 *
 * SSHTTPD is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * SSHTTPD is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @file
 * Provides a response system parsing request structures and sending them
 * to the client.
 */

#define _GNU_SOURCE /* Need this for asprintf. */
/* System includes. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* App includes. */
#include "include/request.h"
#include "include/response.h"
#include "include/file.h"
#include "include/utils.h"
#include "include/socket.h"

char *REQOK = "HTTP/1.1 200 OK";
char *REQBAD = "HTTP/1.1 400 Bad Request";
char *REQNF = "HTTP/1.1 404 Not Found";
char *REQBADTXT = "<html><title>Bad Request</title><body>Bad Request</body></html>";
char *REQNFTXT = "<html><title>Not Found</title><body>Not Found</body></html>";
char *HTTPVER = "HTTP/1.0";

httpresp_t *build_response(httpr_t *request) {
	httpresp_t *resp;
	
	if(!(resp = malloc(sizeof *resp)))
		return NULL;

	memset(resp, '\0', sizeof(*resp));

	/* What request are we going to respond to? */
	switch(request->reqcode) {
		case REQ_HEADER:
			resp->header = 1;
		case REQ_GET:
			if(request->ver)
				resp->ver = HTTPVER;

			/* This works if we assume request.reqcode as REQ_GET is 0 so 
			 * get_file(pretend) is false and REQ_HEADER is not. */
			resp->file = getfile(request->url, 0);

			/* File not found. */
			if(!resp->file) {
				resp->sstring = REQNF;
				resp->file = newfile(REQNFTXT, "text/html", strlen(REQNFTXT));
				break;
			}

			resp->sstring = REQOK;
			break;
		case REQ_ERROR:
		default:
			resp->sstring = REQBAD;
			resp->file = newfile(REQBADTXT, "text/html", strlen(REQBADTXT));
			break;
	}
	return resp;
}

void destroy_response(httpresp_t *resp) {
	if(resp->file)
		destroyfile(resp->file);
	free(resp);
}

int send_response(httpresp_t *resp, int ud) {
       	char *header;
	int hsent, dsent, tsent;

	hsent = dsent = 0;

	if(resp->ver != NULL) {
		asprintf(&header, "%s\r\nServer: %s\r\n", resp->sstring, "SSHTTPD");
		hsent += sendstr(ud, header);
		free(header);

		if(resp->file->ctype != NULL) {
			asprintf(&header, "Content-Type: %s\r\n", resp->file->ctype);
			hsent += sendstr(ud, header);
			free(header);
		}
		if(resp->file->size > 0) {
			asprintf(&header, "Content-Length: %d\r\n", resp->file->size);
			hsent += sendstr(ud, header);
			free(header);
		}
		
		hsent += send(ud, "Connection: close\r\n\r\n", strlen("Connection: close\r\n\r\n"), 0);
	}
	if(resp->file->data != NULL) {
		dsent += send(ud, resp->file->data, resp->file->size, 0);
	}
	
	tsent = hsent + dsent;
	event(ELOG, "sent %d bytes, %d header and %d payload", tsent, hsent, dsent);
	return tsent;
}
